(function(global, factory){
    if(global.define !== undefined)
    {
        // 如果存在其他的AMD加载器则不做任何操作
        return;
    }
    return factory(global);
}(this, function(Global){

    "use strict";

    /**
     * 天命空间 
     * @namespace tm
     */
    
    var version = "1.0.0";

    /** 内部变量 */
    var tm = {};

    /** 外部模块定义 */
    var modules = {};

    /** 外部模块加载地址 */
    var jsLoadUrl = {};

    /** 涵盖所有类型 */
    var class2type = {};

    /** 涵盖所有基本类型 */
    var baseType = {};

    /** 
     * 框架主体
     * @constructor
     * @memberof tm~
     */
    var Lyx = function(){};

    Lyx.debug = false;

    /**
     * 实例化一个模块
     * @param {string} id 模块id
     * @memberof tm~
     */
    function module(id)
    {
        this.init(id);
    }

    /**
     * 枚举
     * @alias tm~module
     * @readonly
     * @enum {number}
     */
    module.STATUS = {

        /** 初始状态 */
        INITIAL: 0,

        /** 请求对列中 */
        REQUEST: 1,

        /** 模块文件刚加载完成 */
        LOADING: 2,

        /** 加载依赖项 */
        LOADDEPS: 3,

        /** 加载完毕，模块可用 */
        SUCCESSFUL: 4
    }

    /**
     * 加载模块
     * @memberof tm~
     * @param {object} call 加载信息
     * @param {string | number} call.id 需要加载的模块id
     * @param {string | number} call.request.id 请求依赖的模块id
     * @param {number} call.request.index 当前模块在请求依赖的模块中的参数位置
     */
    function loadModule(call)
    {
        Lyx.loadJs(jsLoadUrl[call.id], onScriptLoad, {
            moduleName: call.id
        });
        modules[call.id].status = module.STATUS.LOADING;
        modules[call.id].reqDeps.enqueue(call);
    }


    /**
     * 标签onload事件
     * @memberof tm~
     * @callback onScriptLoad
     * @param {object} event 
     */
    function onScriptLoad(event)
    {
        var node = event.currentTarget || event.srcElement;
        var name = node && node.getAttribute("data-moduleName");
        if(modules[name].status != module.STATUS.SUCCESSFUL)
        {
            var args = defQueue.dequeue();
            args[0] = name;
            define.apply(this, args);
        }
    }

    /**
     * 扩展一个对象
     * @memberof tm~
     * @param {any} target 目标对象
     * @param {function| Object[] | Object} obj 要向目标对象添加的属性
     * @param {boolean} [cover = false] 当属性发成冲突时是否覆盖，默认不覆盖
     */
    function extend(target, list, cover)
    {
        for(var i = 0, len = list.length; i < len; i ++)
        {
            if(typeof(list[i]) == "function")
            {
                if(!cover && typeof(target[list[i].name]) != "undefined")
                {
                    console.error(list[i].name + "冲突！");
                    return;
                }
                target[list[i].name] = list[i];
            }
            else if(Object.prototype.toString.call(list[i]) == "[object Array]")
            {
                console.error("扩展未知！");
                return;
            }
            else
            {
                var keys = Object.keys(list[i]);
                for(var j = 0, lenJ = keys.length; j < lenJ; j ++)
                {
                    if(!cover && typeof(target[keys[j]]) != "undefined")
                    {
                        console.error("属性" + keys[j] + "冲突！");
                        return;
                    }
                    target[keys[j]] = list[i][keys[j]];
                }
            }
        }
        return target;
    }

    /**
     * 扩展一个对象，未这只目标对象时，默认对Lyx进行扩展
     * @alias tm.
     * @param {any} [target = Lyx] 目标对象
     * @param {function | Object[] | Object} obj 要向目标对象添加的属性
     * @param {boolean} [cover = false] 当属性发成冲突时是否覆盖
     */
    Lyx.extend = function(target, obj, cover)
    {
        // [undefined, obj, undefined]
        if(typeof(obj) === "undefined")
        {
            obj = target;
            target = Lyx;
        }
        // 扩展Lyx，args{object, boolean}
        else if(typeof(obj) === "boolean")
        {
            cover = obj;
            obj = target;
            target = Lyx;
        }
        if(Object.prototype.toString.call(obj) != "[object Array]")
        {
            obj = [obj];
        }
        return extend(target, obj, cover || false);
    }

    Lyx.extend({
        /**
         * get/set方法，用于对外开放内部私有变量
         * @memberof tm.
         * @returns {object} modules
         */
        getModules: function()
        {
            return modules;
        }
    });

    // 种子模块
    Lyx.extend({
        type: function(obj)
        {
            if ( obj == null )
            {
                return obj + "";
            }
            return typeof obj === "object" || typeof obj === "function" ?
                class2type[toString.call(obj)] || "object" :
                typeof obj;
        },
        isBaseType: function(obj){
            return !Lyx.isUndefined(baseType[Lyx.type(obj)]);
        },
        isUndefined: function(obj)
        {
            return obj === void 0;
        },
        isFunction: function(obj)
        {
            return Lyx.type(obj) === "function";
        },
        isArrayLike: function(obj)
        {
            var type = Lyx.type(obj);
            if ( type === "function" || type === "string")
            {
                return false;
            }

            var length = !!obj && "length" in obj && obj.length;

            return type === "array" || length === 0 ||
                typeof length === "number" && length > 0 && ( length - 1 ) in obj;
        },

        /**
         * 扩展对象原型
         * @param {Object} target 目标对象
         * @param {Object} obj 扩展属性
         */
        p2t: function(target, obj)
        {
            Lyx.each(obj, function(name, value){
                target.prototype[name] = value;
            });
        },

        /**
         * 生成min-max之间的随机整数
         * @param {Number} min 最小值
         * @param {Number} max 最大值
         * @returns {Boolean} 随机数
         */
        random: function(min, max)
        {
            return parseInt(Math.random() * (max - min) + min);
        },

        /**
         * 验证生成的随机字符串是否合法
         * @callback randomStrCheck
         * @param {string} 生成的随机字符串
         * @returns {Boolean} 验证结果
         */

        /**
         * 生成随机字符串[a-z][A-Z][0-9]
         * @param {Number} [length = 4] 随机字符串的长度
         * @param {randomStrCheck} [check = null]
         */
        randomStr: function(length, check)
        {
            length = length || 4;
            check = check || function(){
                return true;
            };
            var dict = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
            var str = "";
            do
            {
                while(length --)
                {
                    str += dict[Lyx.random(0, 62)];
                }
            }while(!check(str))
            return str;
        },

        /**
         * 设置继承关系
         * @param {function} parent 父类
         * @param {function} child 子类
         */
        inherits: function(parent, child)
        {
            var link = function(){};
            link.prototype = parent.prototype;
            var temp = new link();
            Lyx.each(child.prototype, function(name, func){
                temp[name] = func;
            });
            child.prototype = temp;
            child.prototype.constructor = child;
        },

        
        createClass: function(parent, definition)
        {
            if(Lyx.isUndefined(definition))
            {
                definition = parent;
                parent = Object;
            }

            function child()
            {
                var self = this instanceof child ? this : new link();
                self.init.apply(self, arguments);
                return self;
            }

            function link(){};
            link.prototype = parent.prototype;
            child.prototype = new link();
            link.prototype = child.prototype;
            child.prototype.constructor = child;

            child.open = function(def)
            {
                if(Lyx.isFunction(def))
                {
                    def = def.call(child, child.prototype, parent.prototype, child, parent);
                }

                if(Lyx.type(def) === "object")
                {
                    Lyx.each(def, function(name, value){
                        if(Object.prototype.hasOwnProperty.call(def, name))
                        {
                            child.prototype[name] = value;
                        }
                    });
                }

                if(!("init" in child.prototype))
                {
                    child.prototype.init = parent.constructor;
                }

                return child;
            }

            return child.open(definition);
        },

        // 遍历数组或者对象，context可以设置回调函数的上下文
        each: function(obj, callback, context)
        {
            context = context || obj;
            if(Lyx.isArrayLike(obj))
            {
                for(var i = 0, len = obj.length; i < len; i++)
                {
                    if(callback.call(context, i, obj[i]) == false)
                    {
                        break;
                    }
                }
            }
            else
            {
                for(i in obj)
                {
                    if(callback.call(context, i, obj[i]) == false)
                     {
                         break;
                     }
                }
            }
        },
        defaultValue: function(value, defValue)
        {
            if(Lyx.isUndefined(value))
            {
                value = defValue;
            }
            return value;
        }
    });

    // 扩展功能
    Lyx.extend({
        /**
         * 将模块提升为全局变量
         * @param {string | string[]} id 模块id
         * @param {string | string[]} [name] 提升模块中指定属性
         */
        toGlobal: function(id, name)
        {
            if(Lyx.type(id) === "string")
            {
                id = [id];
            }
            require(id, function(){
                var moduleList = arguments;
                if(Lyx.isUndefined(name))
                {
                    Lyx.each(id, function(index, id){
                        Lyx.extend(Global, {
                            [id]: moduleList[index]
                        });
                    });
                }
                else
                {
                    Lyx.each(Lyx.type(name) === "string" ? [name] : name, function(index, name){
                        Lyx.extend(Global, {
                            [name]: moduleList[0][name]
                        });
                    });
                }
            });
        },
        setAlias: function(alias)
        {
            Lyx.extend(Global, {
                [alias]: Lyx
            });
        },
        plugins: function(id)
        {
            if(!Lyx.isArrayLike(id))
            {
                id = [id];
            }
            require(id, function(){
                for(var i = 0, len = arguments.length - 1; i < len; i ++)
                {
                    Lyx.extend(arguments[i]);
                }
            });
        },
        config: function(obj)
        {
            Lyx.each(obj.paths, function(id, path){
                jsLoadUrl[id] = (obj.baseUrl || "") + path + ".js";
                modules[id] = new module(id);
            });
            Lyx.each(obj.url || {}, function(id, path){
                jsLoadUrl[id] = path + ".js";
                modules[id] = new module(id);
            });
        },
        log: function(log, type)
        {
            type = type || "log";
            if(Lyx.debug)
            {
                console[type](log);
            }
            else
            {
                if(type == "error")
                {
                    console.error(log);
                }
                else
                {
                    console[type](log);
                    console.trace(log);
                }
            }
        },
        loadJs: function(src, callback, data)
        {
            var node = document.createElement("script");
            node.src = src;
            node.charset = 'utf-8';
            node.async = true;
            Lyx.each(data, function(name, value){
                node.setAttribute("data-" + name, value);
            });
            document.getElementsByTagName("head")[0].appendChild(node);
            node.onload = callback;
        },
        observeDeep: function(obj, prefix)
        {
            Lyx.observe(obj, prefix, true);
        },
        // 监听一个对象
        observe: function(obj, prefix, deep)
        {
            // 设置扫描前缀，默认为$
            prefix = prefix || "$";
            deep = deep || false;
            var stack = [obj];
            while(stack.length != 0)
            {
                obj = stack.pop();
                Lyx.each(obj, function(key, value){
                    var $ = obj[prefix + key];
                    if(!Lyx.isUndefined($))
                    {
                        (function(obj, key){
                            
                            // 属性默认值
                            var _ = obj[key];
                            $.chmod = $.chmod || "rw";
                            delete obj[key];
                            Object.defineProperty(obj, key, {
                                get: /^r(|w)/.test($.chmod) ? function()
                                {
                                    var value = Lyx.isFunction($.get) ? $.get.call(obj, _, function(value){
                                        Object.defineProperty(obj, key, {
                                            get: function()
                                            {
                                                return _;
                                            }
                                        });
                                        _ = value;
                                        return _;
                                    }) : _;
                                    return Lyx.isUndefined(value) ? _ : value;
                                } : undefined,
                                set: /^(|r)w$/.test($.chmod) ? function(value)
                                {
                                    var ret = Lyx.isFunction($.set) ? $.set.call(obj, value, _) : undefined;
                                    _ = Lyx.isUndefined(ret) ? value : ret;
                                } : undefined,
                                configurable: true
                            });
                        })(obj, key);
                        delete obj[prefix + key];
                    }
                    if(!Lyx.isBaseType(value) && key[0] != prefix)
                    {
                        stack.push(value);
                    }
                });
                if(deep == false)
                {
                    return;
                }
            }
        },

        lock: new function()
        {
            // 记录所有的回调（随机id：idLock）
            var lockCallback = {};

            var idLock = function(context)
            {
                this.init(context);
            }
            Lyx.p2t(idLock, {
                init: function(context)
                {
                    this.lockNum = 0;
                    this.lock = false;
                    this.deps = new Lyx.queue();
                    this.reqDeps = new Lyx.queue();

                    this.$lockNum = {
                        set: function(value)
                        {
                            if(value == 0)
                            {
                                this.lock = false;
                                if(Lyx.isFunction(this.onUnlock))
                                {
                                    this.onUnlock.call(context);
                                }
                            }
                            else if(!this.lock)
                            {
                                this.lock = true;
                                if(Lyx.isFunction(this.onLock))
                                {
                                    this.onLock.call(context);
                                }
                            }
                        }
                    }
                    Lyx.observe(this);
                }
            });
    
            var lock = function(cbId, idList, callback, context)
            {
                // ([], function)
                if(Lyx.type(cbId) !== "string")
                {
                    context = callback;
                    callback = idList;
                    idList = cbId;
                    // 为回调函数生成随机id
                    cbId = Lyx.randomStr(4, function(id){
                        return Lyx.isUndefined(idList[id]);
                    });
                }

                // 初始化锁
                var cbLock = lock.init(cbId, context);

                // 为锁添加解锁回调
                lock.onUnlock(cbId, callback);

                // 遍历所有的依赖，将当前id插入所有依赖项中
                Lyx.each(idList, function(index, id){
                    // 将依赖项置入
                    cbLock.deps.enqueue(id);

                    // 得到依赖项
                    var temp = lock.init(id, context);
                    // 将id置入依赖项中
                    temp.reqDeps.enqueue(cbId);

                    cbLock.lockNum += lock[id] ? 1 : -1;

                    if(Lyx.type(lock[id]) !== "boolean")
                    {
                        throw new Error();
                        return;
                    }
                });
            }
            Lyx.extend(lock, {
                onLock: function(id, callback)
                {
                    lockCallback[id].onLock = callback;
                },
                onUnlock: function(id, callback)
                {
                    lockCallback[id].onUnlock = callback;
                },
                del: function(id)
                {
                    delete lock[id];
                    delete lockCallback[id];
                },
                get: function(id)
                {
                    return lockCallback[id].lock;
                },
                init: function(cbId, context)
                {
                    if(Lyx.isUndefined(lock[cbId]))
                    {
                        var _;
                        lockCallback[cbId] = new idLock(context);
                        var cbLock = lockCallback[cbId];
                        Object.defineProperty(lock, cbId, {
                            set: function(value)
                            {
                                if(value != lock[cbId] || Lyx.isUndefined(lock[cbId]))
                                {
                                    _ = value;
                                    Lyx.each(cbLock.reqDeps, function(index, id){
                                        lock.init(id).lockNum += value ? 1 : -1;
                                    });
                                }
                            },
                            get: function()
                            {
                                return _;
                            }
                        });
                        lock[cbId] = true;
                    }
                    return lockCallback[cbId];
                }
            });
            return lock;
        }
    });

    function define(id, deps, factory)
    {
        if(Lyx.type(id) !== "string")
        {
            if(Lyx.isArrayLike(id))
            {
                factory = deps;
                deps = id;
            }
            else
            {
                factory = id;
                deps = [];
            }
            id = null;
            defQueue.enqueue([id, deps, factory]);
            return;
        }
        if(Lyx.isUndefined(modules[id]))
        {
            console.error(id + "模块未配置！");
            return;
        }
        var mod = modules[id];
        if(modules[id].status != module.STATUS.SUCCESSFUL)
        {
            mod.factory = factory;
            Lyx.each(deps, function(index, depId){
                if(Lyx.isUndefined(jsLoadUrl[depId]))
                {
                    console.error("依赖项" + depId + "不存在！");
                    mod.uninstall = -1;
                    return false;
                }
                if(modules[depId].status == module.STATUS.SUCCESSFUL)
                {
                    // 依赖模块如果已加载则直接将依赖模块实例传入
                    mod.deps.push(modules[depId].instance);
                }
                else
                {
                    // 依赖项未加载完成，传入null占位，防止参数顺序混乱
                    mod.deps.push(null);
                    mod.uninstall ++;
                    
                    // 如果依赖项未被请求加载
                    if(modules[depId].status == module.STATUS.INITIAL)
                    {
                        //将未加载的模块传入加载队列
                        modules[depId].status = module.STATUS.REQUEST;
                        loadModule({
                            id: depId,
                            request:{
                                id: id,
                                index: index
                            }
                        });
                    }
                    else
                    {
                        modules[depId].reqDeps.enqueue({
                            id: depId,
                            request:{
                                id: id,
                                index: index
                            }
                        });
                    }
                }
            });
            if(mod.uninstall == 0)
            {
                mod.install();
            }
            else
            {
                mod.status = module.STATUS.LOADDEPS;
            }
        }
        else
        {
            console.error(id + "模块重定义！");
        }
    }
    define.amd = {};

    // 调用模块
    function require(deps, callback)
    {
        // 为匿名模块生成随机id
        var id = Lyx.randomStr(4, function(id){
            return Lyx.isUndefined(modules[id]);
        });

        // 为当前模块分配模块实例
        modules[id] = new module(id);
        modules[id].status = module.STATUS.LOADING;

        define(id, deps, callback);
    }

    Lyx.p2t(module, {
        init: function(id)
        {
            this.id = id;           // 模块唯一id
            this.factory;           // 模块工厂
            this.deps = [];         // 依赖项实例，顺序对应于factory的参数表
            this.uninstall = 0;     // 依赖项未安装数目
            this.reqDeps = new Lyx.queue();
            this.status = module.STATUS.INITIAL;
        },

        // 当依赖模块有安装好的会调用该方法
        setDep: function(call)
        {
            this.deps[call.request.index] = modules[call.id].instance;
            this.uninstall --;
    
            if(this.uninstall == 0)
            {
                // 依赖模块都准备完毕，则安装当前模块
                this.install();
            }
        },

        // 安装模块
        install: function()
        {
            // 将当前模块安装到框架中，最后的位置添加Lyx参数
            this.deps.push(Lyx);
            this.instance = this.factory.apply(this, this.deps);
            this.status = module.STATUS.SUCCESSFUL;
            this.callDeps();
        },

        // 通知请求依赖的模块当前模块已加载完毕
        callDeps: function()
        {
            var length = this.reqDeps.length;
            while(length --)
            {
                var call = this.reqDeps.dequeue();
                modules[call.request.id].setDep(call);
            }
        }
    });

    // 计算出所有类型
    Lyx.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),
    function(i, name){
        class2type["[object " + name + "]"] = name.toLowerCase();
    });

    // 设置基本类型
    Lyx.each("boolean number string function".split(" "), function(index, type){
        baseType[type] = true;
    });

    Lyx.queue = Lyx.createClass(Array, function(p2t){
        p2t.init = function(obj)
        {
            Lyx.each(obj, function(name, func){
                this[name] = func;
            }, this);
        };
        p2t.enqueue = function(obj)
        {
            !Lyx.isFunction(this.onEnqueue) || this.onEnqueue(obj);
            return this.push(obj);
        };
        p2t.dequeue = function()
        {
            var temp = this.shift();
            !Lyx.isFunction(this.onDequeue) || this.onDequeue(temp);
            return temp;
        };
        p2t.empty = function()
        {
            while(this.length != 0)
            {
                this.pop();
            }
        };
    });

    // 加载配置文件
    var defQueue = new Lyx.queue();
    var config = document.currentScript.getAttribute("data-config");
    Lyx.loadJs(config, function(){
        Lyx.config.ready = true;
    });

    // 注册全局变量
    Lyx.extend(Global, [define, require]);
    
    Lyx.extend(Global, {
        Lyx: Lyx
    });
    return Lyx;
}));